from Level import Level 
from libavg import avg, ui
from libavg.ui.button import TouchButton
import Constants
import os
import xml.dom.minidom as dom

class GameBoard(avg.DivNode):

    def __init__(self, parent, game, players=1, **kwargs):
        super(GameBoard, self).__init__(**kwargs)
        
        self.__game = game

        if parent:
            parent.appendChild(self)
            
        self.size = Constants.RESOLUTION

        self.__players = players
        self.__stage = -1
        self.__level = None
        self.__reload = False
        self.__btns = []
        self.__bgr = avg.ImageNode(href = "resources/textures/help/bgr.png", parent=self, size=self.size)
        self.__btnDiv = avg.DivNode(parent=self)
        self.__levelChooser = ui.TransformRecognizer(
                eventNode=self.__btnDiv, 
                moveHandler=self.__onLevelChooserMove,
                friction=0.08
        )
        
        self.__closeBtn = TouchButton (
            parent = self,
            pos = (Constants.RESOLUTION.x - 60, Constants.RESOLUTION.y - 50 - 10),
            size=(50,50),
            upNode = avg.ImageNode(href = "resources/textures/menu/btn_exit.png", size=(50, 50)),
            downNode = avg.ImageNode(href = "resources/textures/menu/btn_exit_d.png", size=(50, 50)),
            clickHandler = lambda: self.__game.showMenu()) 
        
        self.show()
        
        self.__story = avg.DivNode(parent=self, size=Constants.RESOLUTION)
        self.__storyMusic = avg.SoundNode(parent=self, loop=True, volume=Constants.STORY_VOL)
        self.__storyBgr = avg.ImageNode(href="resources/textures/story/book.png", parent=self.__story, size=Constants.RESOLUTION)
        self.__storyImage = avg.ImageNode(href="resources/textures/story/book.png", parent=self.__story, pos=(128,69), size=(438,325), angle = -(Constants.DEGREE2RAD * 5.5))
        self.__storyText = avg.WordsNode(pos=(950,50), font="Courier New", wrapmode="word", variant="Bold", fontsize=18, color="000000", alignment="center", parent=self.__story, size=(600,0))
        self.__levelText = avg.WordsNode(pos=(330,530), font="Courier New", wrapmode="word", variant="Bold", fontsize=26, color="000000", alignment="center", parent=self.__story, size=(600,0))

        self.__storyButton = ui.HoldRecognizer(node=self.__story, delay=1000, detectedHandler=self.__onStoryClick)     
        self.__story.active = False
        self.__isPreStory = True
    
    def __onLevelChooserMove(self, transform):
        transform.scale = 1
        transform.rot = 0
        transform.moveNode(self.__btnDiv)
        self.__btnDiv.pos = (0, self.__btnDiv.pos.y)
        if self.__btnDiv.pos.y > 0:
            self.__btnDiv.pos = (self.__btnDiv.pos.x, 0)
        elif self.__btnDiv.pos.y + self.__btnDiv.size.y < 800:
            self.__btnDiv.pos = (self.__btnDiv.pos.x, -(self.__btnDiv.size.y - 800))
    
    def abortLevel(self):
        self.__storyMusic.stop()
        self.__storyMusic.volume = Constants.STORY_VOL
        
        self.__level.leave()
        self.__level.destroy()
        
        self.show()
    
    def endLevel(self, finished):
        self.__storyMusic.stop()
        self.__storyMusic.volume = Constants.STORY_VOL
        
        self.__level.leave()
        
        self.__reload = True
        
        if self.__players == 1 and finished:
            self.__updateXMLAttributes()
            self.__showEpilog()
        elif self.__players == 2:
            self.__showBattleResults()
        else:
            self.show()

        self.__level.destroy()
        
    def __updateXMLAttributes(self):
        #Change some attributes of current level xml
        self.__levelXml.setAttribute("finished", (1).__str__())
            
        highscore = eval("int("+self.__levelXml.getAttribute("points")+")")
        highscore = max(highscore, self.__level.actors[0].score)
        self.__levelXml.setAttribute("points", highscore.__str__())
        xmlstr = self.__levelXml.toprettyxml(encoding='utf-8')
        
        outFile = "resources/levels/sp/"+self.__stage.__str__()+".xml"
        f = open(outFile, 'w')
        f.write(xmlstr)
        f.close() 
        
        #Set next level playable
        in_directory = "resources/levels/sp"
        joiner = (in_directory + os.path.sep).__add__
        levelCount = sum(
            os.path.isfile(filename)
            for filename
            in map(joiner, os.listdir(in_directory))
            )  
        
        if levelCount > self.__stage:
            nXML =  dom.parse((in_directory + os.path.sep) + (self.__stage+1).__str__() + ".xml")
            lXML = nXML.getElementsByTagName("level")[0]
            lXML.setAttribute("playable", (1).__str__())
            outFile = "resources/levels/sp/" + (self.__stage+1).__str__() + ".xml"
            f = open(outFile, 'w')
            xmlstr = lXML.toprettyxml(encoding='utf-8')
            f.write(xmlstr)
            f.close() 
    
    def startLevel(self, xml, levelId):
        self.__stage = levelId
        self.__game.mute()
        
        self.__story.active = False
        self.__levelXml = xml
        
        self.__showProlog()

    def __activateLevel(self):
        self.__story.active = False
        self.__level = Level(parent=self, xml=self.__levelXml)
        
        self.__storyMusic.href = "resources/sound/ingame.mp3"
        self.__storyMusic.volume = Constants.INGAME_VOL
        self.__storyMusic.play()
        
        self.__level.enter()
    
    def __showProlog(self):
        self.__bgr.active = False
        self.__btnDiv.active = False
        self.__closeBtn.active = False
        for b in self.__btns:
            b.active = False
        
        prolog = self.__levelXml.getElementsByTagName("prolog")
        prologImage = prolog[0].getAttribute("img") if prolog else ""
        prologText = prolog[0].getElementsByTagName("text")[0].firstChild.wholeText if prolog else ""
        prologSound = prolog[0].getAttribute("sound") if prolog else ""

        self.__storyImage.href = prologImage
        self.__storyText.text = prologText
        self.__storyMusic.href = prologSound
        self.__levelText.text = "Level: " + self.__stage.__str__()
        
        if prologImage != "" or prologText != "":
            self.__story.active = True
            
        if prologSound != "":
            self.__storyMusic.play()
        
        if self.__story.active == False:
            self.__activateLevel()
            
        self.__isPreStory = True
        
    def __showEpilog(self):
        self.__bgr.active = False
        self.__btnDiv.active = False
        self.__closeBtn.active = False
        for b in self.__btns:
            b.active = False
            
        epilog = self.__levelXml.getElementsByTagName("epilog")
        epilogImage = epilog[0].getAttribute("img") if epilog else ""
        epilogText = epilog[0].getElementsByTagName("text")[0].firstChild.wholeText if epilog else ""
        epilogSound = epilog[0].getAttribute("sound") if epilog else ""
        
        self.__storyImage.href = epilogImage
        self.__storyText.text = epilogText
        self.__storyMusic.href = epilogSound
        self.__levelText.text = "Level: " + self.__stage.__str__() + "<br/>- ACCOMPLISHED -"
        
        if epilogImage != "" or epilogText != "":
            self.__story.active = True
            
        if epilogSound != "":
            self.__storyMusic.play()
            
        if self.__story.active == False:
            self.show()    

        self.__isPreStory = False
        
    def __showBattleResults(self):
        self.__bgr.active = False
        self.__btnDiv.active = False
        self.__closeBtn.active = False
        for b in self.__btns:
            b.active = False
            
        actors = self.__level.actors
        scoreYellow = actors[0].score
        scoreRed = actors[1].score

        epilogText = "<br/><br/><br/><br/>That was legen...<br/><br/><br/><br/>...wait for it...<br/><br/><br/><br/>...dary!!! :)<br/><br/><br/><br/><br/><br/><br/><b>Red: " + scoreRed.__str__() + " Points</b><br/><br/>Vs.<br/><br/><b>Yellow:</b> " + scoreYellow.__str__() + " Points"
        epilogSound = ""
        
        if scoreYellow == scoreRed:
            epilogImage = "resources/textures/story/multiplayer_2.png"
            winnerStr = "DRAW"
        elif scoreYellow > scoreRed:
            epilogImage = "resources/textures/story/multiplayer_0.png"
            winnerStr = "YELLOW WINS"
        else:
            epilogImage = "resources/textures/story/multiplayer_1.png"
            winnerStr = "RED WINS"

        self.__levelText.text = winnerStr
        self.__storyImage.href = epilogImage
        self.__storyText.text = epilogText
        self.__storyMusic.href = epilogSound
        
        if epilogImage != "" or epilogText != "":
            self.__story.active = True
            
        if epilogSound != "":
            self.__storyMusic.play()
            
        if self.__story.active == False:
            self.show()    

        self.__isPreStory = False
    
    def __onStoryClick(self, event):
        self.__story.active = False
        self.__storyMusic.stop()

        if self.__isPreStory == True:
            self.__activateLevel()
        else:
            self.show()
    
    def show(self):
        self.__game.unmute()
        
        ###In case xml attributes have changed
        if self.__reload == True:
            in_directory = "resources/levels/" + ("mp" if self.__players > 1 else "sp")
                        
            joiner = (in_directory + os.path.sep).__add__
            levelCount = sum(
                os.path.isfile(filename)
                for filename
                in map(joiner, os.listdir(in_directory))
                )
            
            for b in self.__btns:
                b.destroy()
            
            self.__btnDiv.pos = (0,0)
            self.__btnDiv.size = (1280, 800 * (levelCount / 12) + (800 if levelCount % 12 > 0 else 0))       
            self.__btns = []
            
            i = 1
            while i <= levelCount:
                game =  dom.parse((in_directory + os.path.sep) + i.__str__() + ".xml")
                lxml = game.getElementsByTagName("level")
                self.__btns.append(LevelButton(parent=self.__btnDiv, board=self, levelId=i, xml=lxml[0]))
                i += 1
            self.__reload = False
            
        self.__bgr.active = True
        self.__btnDiv.active = True
        self.__closeBtn.active = True
        for b in self.__btns:
            b.active = True
            
    def setPlayers(self, players):
        self.__reload = True
        self.__players = players
        
    def getPlayers(self):
        return self.__players

class LevelButton(avg.DivNode):
    
    __btnSize = avg.Point2D(150,150)
    
    def __init__(self, parent, board, levelId, xml, **kwargs):
        super(LevelButton, self).__init__(**kwargs)
        
        if parent:
            parent.appendChild(self)
            self.__parentNode = parent
            
        self.__levelId = levelId    
        self.__board = board
        self.__xml = xml

        self.__customized = eval("int("+self.__xml.getAttribute("customized")+")") == 1
        self.__finished = eval("int("+self.__xml.getAttribute("finished")+")") == 1
        self.__playable = eval("int("+self.__xml.getAttribute("playable")+")") == 1
        self.__points = eval("int("+self.__xml.getAttribute("points")+")")
        
        players = self.__xml.getElementsByTagName("actor")
            
        self.size = self.__btnSize
        self.pos = ((Constants.RESOLUTION.x / 4) * ((levelId-1) % 4) + self.size.x/2, (Constants.RESOLUTION.y / 3) * ((levelId-1) / 4) + self.size.y/2)
    
        self.__btnTex = avg.DivNode(parent=self, size=self.__btnSize)
        self.__tex = avg.ImageNode(parent=self.__btnTex, size=self.__btnSize, gamma = (1.0, 1.0, 1.0))
        self.__tex.setBitmap(avg.SVG('resources/textures/menu/LevelButton.svg', False).renderElement('Layer1'))
        self.__btnId = avg.WordsNode(parent=self.__btnTex, pos=(self.__btnSize.x/2,self.__btnSize.y/2-20), text=levelId.__str__() + ("(C)" if self.__customized == True else ""), font="Courier New", wrapmode="word", variant="Bold", fontsize=40, color="000000", alignment="center")
        
        self.__btnPoints = None
        if self.__finished == True and players.__len__() == 1:
            self.__btnPoints = avg.WordsNode(parent=self.__btnTex, pos=(self.__btnSize.x/2,self.__btnSize.y-40), text=self.__points.__str__(), font="Courier New", wrapmode="word", variant="Bold", fontsize=30, color="FFFFFF", alignment="center")

        if self.__customized == True:
            self.__tex.intensity = (0.8, 0.3, 0.0)
        elif self.__finished == True:
            self.__tex.intensity = (0.0, 0.8, 0.0)
        elif self.__playable == True:
            self.__tex.intensity = (0.8, 0.8, 0.0)
        
        self.__touchRecognizer = ui.TapRecognizer (
                node=self.__btnTex, 
                detectedHandler=self.__startLevel            
        )
        
    def __startLevel(self, event):
        if self.__playable == True or self.__customized == True:
            self.__board.startLevel(self.__xml, self.__levelId)    
    
    def destroy(self):
        self.__touchRecognizer.enable(False)
        self.__touchRecognizer = None
        self.__xml = None
        if self.__btnPoints is not None:
            self.__btnPoints.unlink(True)
            self.__btnPoints = None
        self.__btnId.unlink(True)
        self.__btnId = None
        self.__tex.unlink(True)
        self.__tex = None
        self.__btnTex.unlink(True)
        self.__btnTex = None
        self.unlink(True) 